//
//  IMConversationViewController.m
//  MLIM
//
//  Created by molon on 15/6/25.
//  Copyright (c) 2015年 molon. All rights reserved.
//

#import "IMConversationViewController.h"
#import "IMCommon.h"
#import "IMTextMessageTableViewCell.h"
#import "IMAudioMessageTableViewCell.h"
#import "IMImageMessageTableViewCell.h"
#import "IMChatInputView.h"
#import <HPGrowingTextView.h>
#import <MLAmrPlayManager.h>
#import "IMChatMoreView.h"
#import <MLAudioPlayButton.h>
#import "IMConversationListViewController.h"
#import "IMMessageLoadMoreTableViewCell.h"
#import "HPTextViewInternal+OverrideNextResponder.h"
#import "IMMessageBackgroundImageView.h"

#define kDisplayDateInterval 3*60 //3分钟的显示日期间隔
#define kLoadMoreCellHeight 60.0f
static NSDictionary * kIMMessageClassToCellClassMap() {
    static NSDictionary *_IMMessageClassToCellClassMap = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _IMMessageClassToCellClassMap = @{
                                          NSStringFromClass([IMTextMessage class]):[IMTextMessageTableViewCell class],
                                          NSStringFromClass([IMAudioMessage class]):[IMAudioMessageTableViewCell class],
                                          NSStringFromClass([IMImageMessage class]):[IMImageMessageTableViewCell class],
                                          };
    });
    
    return _IMMessageClassToCellClassMap;
}

@interface IMConversationViewController ()<UIGestureRecognizerDelegate>

@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) NSMutableArray *imMessages;
@property (nonatomic, strong) IMChatInputView *chatInputView;
@property (nonatomic, strong) IMChatMoreView *chatMoreView;
@property (nonatomic, strong) UITapGestureRecognizer *tabelViewTapGesture;


//当前是否需要懒加载，是在数据加载完毕之后设置YES，以用来隐藏加载中的cell
@property (nonatomic, assign) BOOL dontNeedLazyLoad;
//当前是否禁用懒加载，防止重复进入到willDisplay的 delegate 方法里重复请求新数据
@property (nonatomic, assign) BOOL disableLazyLoad;
//load more的cell
@property (nonatomic, strong) IMMessageLoadMoreTableViewCell *moreCell;
//需要插入到头部的消息，用来在tableView非触摸和滚动时候加载
@property (nonatomic, strong) NSArray *needInsertTopIMMessages;

//当前menu启用的背景View
@property (nonatomic, weak) IMMessageTableViewCell *currentMenuCell;

@property (nonatomic, strong) MLAudioPlayButton *audioAutoPlayButton;

@end

@implementation IMConversationViewController

- (instancetype)init
{
    self = [super init];
    if (self) {
        
        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(detailUpdated:) name:MLIM_IMConversation_UpdateDetail_Notification object:nil];
        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(newMessage:) name:MLIM_IMConversation_NewMessages_Notification object:nil];
        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(imcmCleaned:) name:MLIM_IMConversationManager_Clean_Notification object:nil];
        
        
        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(mlAmrPlayerPlayStopped:) name:MLAMRPLAYER_PLAY_RECEIVE_STOP_NOTIFICATION object:nil];
        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(mlAmrPlayerPlayStart:) name:MLAMRPLAYER_PLAY_RECEIVE_START_NOTIFICATION object:nil];
        
        
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(menuWillHide:)
                                                     name:UIMenuControllerWillHideMenuNotification object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(menuWillShow:)
                                                     name:UIMenuControllerWillShowMenuNotification object:nil];
        
    }
    return self;
}

- (void)dealloc
{
    DLOG_DEALLOC
    
    [[NSNotificationCenter defaultCenter]removeObserver:self name:UIMenuControllerWillHideMenuNotification object:nil];
    [[NSNotificationCenter defaultCenter]removeObserver:self name:UIMenuControllerWillShowMenuNotification object:nil];
    
    [[NSNotificationCenter defaultCenter]removeObserver:self name:MLAMRPLAYER_PLAY_RECEIVE_STOP_NOTIFICATION object:nil];
    [[NSNotificationCenter defaultCenter]removeObserver:self name:MLAMRPLAYER_PLAY_RECEIVE_START_NOTIFICATION object:nil];
    
    [[NSNotificationCenter defaultCenter]removeObserver:self name:MLIM_IMConversationManager_Clean_Notification object:nil];
    [[NSNotificationCenter defaultCenter]removeObserver:self name:MLIM_IMConversation_NewMessages_Notification object:nil];
    [[NSNotificationCenter defaultCenter]removeObserver:self name:MLIM_IMConversation_UpdateDetail_Notification object:nil];
}

#pragma mark - notification
- (void)detailUpdated:(NSNotification*)notification
{
    NSArray *imConvs = notification.userInfo[@"imConvs"];
    for (IMConversation *imConv in imConvs) {
        if ([imConv.conversationId isEqualToString:self.imConv.conversationId]) {
            self.title = imConv.name;
            break;
        }
    }
}

- (void)newMessage:(NSNotification*)notification
{
    IMConversation *imConv = notification.userInfo[@"imConv"];
    if ([imConv.conversationId isEqualToString:self.imConv.conversationId]) {
        NSArray *imMessages = notification.userInfo[@"imMessages"];
        [self addIMMessages:imMessages];
    }
}

- (void)imcmCleaned:(NSNotification*)notification
{
    //消失自身
    [self disappearSelfWithAnimated:NO];
}

- (void)mlAmrPlayerPlayStopped:(NSNotification*)notification
{
    //找到当前播放的音频
    NSDictionary *userInfo = notification.userInfo;
    if (![userInfo[@"playComplete"]boolValue]) {
        return;
    }
    id extra = userInfo[@"extra"];
    if (![extra isKindOfClass:[NSURL class]]) {
        return;
    }
    
    NSInteger index = [self imAudioMessageIndexWithAuidoURL:extra];
    if (index==NSNotFound) {
        return;
    }
    
    for (NSInteger i=index+1; i<self.imMessages.count; i++) {
        IMMessage *imMsg = self.imMessages[i];
        if (![imMsg isKindOfClass:[IMAudioMessage class]]||!CHILD(IMAudioMessage, imMsg).unheared) {
            continue;
        }
        //播放丫的
        [self.audioAutoPlayButton setAudioWithURL:CHILD(IMAudioMessage, imMsg).audioURL withAutoPlay:YES];
        break;
    }
}


- (void)mlAmrPlayerPlayStart:(NSNotification*)notification
{
    //找到当前播放的音频
    NSDictionary *userInfo = notification.userInfo;
    id extra = userInfo[@"extra"];
    if (![extra isKindOfClass:[NSURL class]]) {
        return;
    }
    
    NSInteger index = [self imAudioMessageIndexWithAuidoURL:extra];
    if (index==NSNotFound) {
        return;
    }
    [CHILD(IMAudioMessage, self.imMessages[index]) setHeared];
}

#pragma mark - view
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    NSAssert(![NSString IsNilOrEmpty:self.imConv.conversationId], @"必须为有效的imConv");
    
    if (![self.imConv isHaveDetail]) {
        [IMCM configureDetailForIMConversations:@[self.imConv] callback:nil];
    }
    
    self.title = self.imConv.name;
    
    self.view.backgroundColor = IMCONFIGM.backgroundColorForIMConversationViewController;
    [self.view addSubview:self.tableView];
    
    //必须先配置下按钮
    self.chatMoreView.combinations = [self combinationsOfChatMoreView];
    
    [self.view addSubview:self.chatInputView];
    
    //如果最后一条是草稿消息就直接搞上去，//TODO 或许应该是最后一条我发过去的消息是草稿消息才合理
    if ([self.imConv.lastMessage isKindOfClass:[IMTextDraftMessage class]]) {
        //最后一条是草稿消息
        self.chatInputView.textView.text = CHILD(IMTextDraftMessage, self.imConv.lastMessage).content;
        self.chatInputView.inputMode = IMChatInputModeKeyboard;
        dispatch_async(dispatch_get_main_queue(), ^{
            [CATransaction setDisableActions:YES];
            [self.chatInputView.textView refreshHeight];
            [CATransaction setDisableActions:NO];
        });
    }
    
    NSArray *initIMMessages = [IMCM cacheMessagesWithIMConvId:self.imConv.conversationId];
    [self configureDisplayDateForIMMessages:initIMMessages withInitLastDisplayTime:0];
    [self.imMessages addObjectsFromArray:initIMMessages];
    
    [self.tableView reloadData];
    
    [self scrollToBottomIndexPathWithAnimated:NO];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    
    //录音停止
    [self.chatInputView stopIfRecording];
    
    //设置草稿消息
    if (self.chatInputView.inputMode!=IMChatInputModeVoice&&![NSString IsNilOrEmpty:self.chatInputView.textView.text]) {
        if([self.imConv.lastMessage isKindOfClass:[IMTextDraftMessage class]]&&[CHILD(IMTextDraftMessage, self.imConv.lastMessage).content isEqualToString:self.chatInputView.textView.text]){ //如果之前就是草稿，而且草稿内容也没变过就不做处理了
            return;
        }
        [IMCM configureTextDraftMessageWithContent:self.chatInputView.textView.text toIMConvId:self.imConv.conversationId];
    }else if([self.imConv.lastMessage isKindOfClass:[IMTextDraftMessage class]]){
        [IMCM configureLastMessage:[self.imMessages lastObject] toIMConvId:self.imConv.conversationId];
    }
}

- (void)viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear:animated];
    //语音停止播放
    [[MLAmrPlayManager manager]stopPlaying];
    [self.audioAutoPlayButton cancelAudioRequestOperation];
    
    //清除当前显示的会话ID
    IMCM.currentDisplayIMConvId = nil;
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    
    //设置当前显示的会话ID
    IMCM.currentDisplayIMConvId = self.imConv.conversationId;
    
    //清零未读数
    [IMCM clearUnreadCountWithIMConvId:self.imConv.conversationId];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (BOOL)hidesBottomBarWhenPushed {
    if (!self.navigationController) {
        return NO;
    }
    
    UIViewController *vc = self;
    while (![self.navigationController isEqual:vc.parentViewController]) {
        vc = vc.parentViewController;
    }
    
    return [[self.navigationController.viewControllers firstObject] isEqual:vc]?NO:[self.navigationController.topViewController isEqual:vc];
}

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
    [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
    
    NSAssert(duration<0, @"IMConversationViewController界面不支持旋转，请相应处理好");
}

#pragma mark - layout
- (void)viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];
    
    [self adjustLayoutWithScrollToBottom:NO];
}

- (void)adjustLayoutWithScrollToBottom:(BOOL)scrollToBottom
{
    CGFloat preferredInputViewHeight = [self.chatInputView preferredHeight];
    self.tableView.frame = CGRectMake(0, 0, self.view.frameWidth, self.view.frameHeight-preferredInputViewHeight);
    self.chatInputView.frame = CGRectMake(0, self.tableView.frameBottom, self.view.frameWidth, preferredInputViewHeight);
    if (scrollToBottom) {
        [self scrollToBottomIndexPathWithAnimated:NO];
    }
}

#pragma mark - getter
- (NSMutableArray *)imMessages
{
    if (!_imMessages) {
        _imMessages = [NSMutableArray new];
    }
    return _imMessages;
}

- (UITapGestureRecognizer *)tabelViewTapGesture
{
    if (!_tabelViewTapGesture) {
        _tabelViewTapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(cancelInput)];
        _tabelViewTapGesture.cancelsTouchesInView = NO;
        _tabelViewTapGesture.delegate = self;
    }
    return _tabelViewTapGesture;
}


- (UITableView *)tableView
{
    if (!_tableView) {
        UITableView *tableView = [[UITableView alloc]init];
        tableView.delegate = self;
        tableView.dataSource = self;
        tableView.backgroundColor = [UIColor clearColor];
        
        tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
        tableView.scrollsToTop = YES;
        [tableView addGestureRecognizer:self.tabelViewTapGesture];
        
        for (Class cls in [kIMMessageClassToCellClassMap() allValues]) {
            [tableView registerClass:cls forCellReuseIdentifier:[NSString stringWithFormat:@"L_%@",[cls cellReuseIdentifier]]];
            [tableView registerClass:cls forCellReuseIdentifier:[NSString stringWithFormat:@"R_%@",[cls cellReuseIdentifier]]];
        }
        
        [tableView registerClass:[IMMessageLoadMoreTableViewCell class] forCellReuseIdentifier:[IMMessageLoadMoreTableViewCell cellReuseIdentifier]];
        
        _tableView = tableView;
    }
    return _tableView;
}

- (IMChatMoreView *)chatMoreView
{
    if (!_chatMoreView) {
        _chatMoreView = [IMChatMoreView new];
    }
    return _chatMoreView;
}

- (IMChatInputView *)chatInputView
{
    if (!_chatInputView) {
        _chatInputView = [[IMChatInputView alloc]initWithMoreView:self.chatMoreView];
        WEAKSELF
        [_chatInputView setPreferredHeightChangedBlock:^(IMChatInputView *chatInputView, BOOL shouldAnimate,UIViewAnimationCurve animationCurve,CFTimeInterval animationDuration) {
            STRONGSELF
            if (shouldAnimate) {
                [UIView beginAnimations:nil context:NULL];
                [UIView setAnimationDuration:animationDuration];
                [UIView setAnimationCurve:animationCurve];
                [UIView setAnimationBeginsFromCurrentState:YES];
                //使用这种方式而不使用layoutIfNeed，是因为layoutIfNeed会对所有子View的子View...做动画，引起怪异效果，但是这个的话，因为不会对子View的子View...做动画，所以里面的像inputPanel的动画需要我们自己做
                [sSelf adjustLayoutWithScrollToBottom:YES];
                
                [UIView commitAnimations];
            }else{
                [sSelf adjustLayoutWithScrollToBottom:YES];
            }
            
        }];
        
        [_chatInputView setSendContentMessageBlock:^(NSString *content) {
            STRONGSELF
            while (![NSString IsNilOrEmpty:content]) {
                NSString *subContent = [content substringWithRange:NSMakeRange(0, MIN(content.length,IM_TextMessageMaxContentLength))];
                
                if (![NSString IsNilOrEmpty:subContent]) {
                    IMTextMessage *imMsg = [IMTextMessage new];
                    imMsg.content = subContent;
                    [sSelf replyIMMessage:imMsg];
                }else{
                    break;
                }
                
                content = [content substringWithRange:NSMakeRange(subContent.length, content.length-subContent.length)];
            }
        }];
        
        [_chatInputView setSendAudioMessageBlock:^(NSURL *filePath, NSTimeInterval duration) {
            STRONGSELF
            IMAudioMessage *imMsg = [IMAudioMessage new];
            imMsg.audioURL = filePath;
            imMsg.duration = duration;
            [sSelf replyIMMessage:imMsg];
        }];
        
    }
    return _chatInputView;
}

- (MLAudioPlayButton *)audioAutoPlayButton
{
    if (!_audioAutoPlayButton) {
        _audioAutoPlayButton = [MLAudioPlayButton new];
    }
    return _audioAutoPlayButton;
}

#pragma mark - gesture
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    if ([gestureRecognizer isEqual:self.tabelViewTapGesture]) {
        CGPoint location = [touch locationInView:gestureRecognizer.view];
        UIView *view = [gestureRecognizer.view hitTest:location withEvent:nil];
        if ([view isKindOfClass:[MLLinkLabel class]]) {
            if ([((MLLinkLabel*)view) linkAtPoint:[touch locationInView:view]]) {
                return NO;
            }
        }else if ([view isKindOfClass:[MLAudioPlayButton class]]){
            return NO;
        }
    }
    return YES;
}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
    if ([gestureRecognizer isEqual:self.tabelViewTapGesture]) {
        if (self.chatInputView.inputMode!=IMChatInputModeVoice&&self.chatInputView.inputMode!=IMChatInputModeNone) {
            return YES;
        }
        return NO;
    }
    
    return YES;
}

#pragma mark - tableview
- (Class)cellClassOfMessage:(IMMessage*)message
{
    return kIMMessageClassToCellClassMap()[NSStringFromClass([message class])];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.imMessages.count+1;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row==0) {
        if (!self.moreCell) {
            IMMessageLoadMoreTableViewCell *moreCell = [tableView dequeueReusableCellWithIdentifier:[IMMessageLoadMoreTableViewCell cellReuseIdentifier] forIndexPath:indexPath];
            WEAKSELF
            [moreCell setClickRetryButtonBlock:^{
                STRONGSELF
                [sSelf doSearchForNextPage];
            }];
            self.moreCell = moreCell;
        }
        
        return self.moreCell;
    }
    
    IMMessage *imMessage = self.imMessages[indexPath.row-1];
    Class cellCls = [self cellClassOfMessage:imMessage];
    
    NSString *cellReuseIdentifier = nil;
    if (IMISME(imMessage.clientId)) {
        cellReuseIdentifier = [NSString stringWithFormat:@"R_%@",[cellCls cellReuseIdentifier]];
    }else{
        cellReuseIdentifier = [NSString stringWithFormat:@"L_%@",[cellCls cellReuseIdentifier]];
    }
    IMMessageTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellReuseIdentifier forIndexPath:indexPath];
    
//    cell.backgroundColor = indexPath.row%2?[UIColor yellowColor]:[UIColor redColor];
    
    cell.imMessage = imMessage;
    
    if (!cell.backgroundImageViewLongPressedBlock) {
        WEAKSELF
        [cell setBackgroundImageViewLongPressedBlock:^(IMMessageTableViewCell *cell) {
            STRONGSELF
            [sSelf longPressBackgroundImageViewWithCell:cell];
        }];
    }
    
    if (!cell.backgroundImageViewTappedBlock) {
        WEAKSELF
        [cell setBackgroundImageViewTappedBlock:^(IMMessageTableViewCell *cell) {
           STRONGSELF
            [sSelf tapBackgroundImageViewWithCell:cell];
        }];
    }
    
    if (!cell.didTappedAvatarBlock) {
        WEAKSELF
        [cell setDidTappedAvatarBlock:^(IMUser *imUser) {
            STRONGSELF
            if (IMUM.didTappedAvatarBlock) {
                IMUM.didTappedAvatarBlock(imUser,sSelf);
            }
        }];
    }
    
    if (!cell.didClickLinkURLBlock) {
        WEAKSELF
        [cell setDidClickLinkURLBlock:^(NSURL *url) {
            STRONGSELF
            if (IMCM.didClickLinkURLBlock) {
                IMCM.didClickLinkURLBlock(url,sSelf);
            }
        }];
    }
    
    if ([cell isKindOfClass:[IMImageMessageTableViewCell class]]) {
        IMImageMessageTableViewCell *imageCell = CHILD(IMImageMessageTableViewCell, cell);
        if (!imageCell.showPictureBlock) {
            WEAKSELF
            [imageCell setShowPictureBlock:^(IMImageMessageTableViewCell *cell) {
                STRONGSELF
                [sSelf showPicturesWithIMImageMessage:CHILD(IMImageMessage, cell.imMessage)];
            }];
        }
    }
    
    return cell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row==0) {
        if (self.dontNeedLazyLoad) {
            return 0.0f;
        }
        return kLoadMoreCellHeight;
    }
    
    IMMessage *imMessage = self.imMessages[indexPath.row-1];
    if (imMessage.heightForCell>0) {
        return imMessage.heightForCell;
    }
    
    Class cellCls = [self cellClassOfMessage:imMessage];
    NSAssert(cellCls, @"无效的IMMessage cellCls");
    
    CGFloat cellHeight = [cellCls heightOfMessage:imMessage maxWidth:self.view.frameWidth];
    imMessage.heightForCell = cellHeight;
    return cellHeight;
}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    if ([scrollView isEqual:self.tableView]) {
        [self cancelInput];
    }
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    if (self.needInsertTopIMMessages) {
        //扔到下一个runloop里心里舒坦，强迫症
        dispatch_async(dispatch_get_main_queue(), ^{
            [self insertTopAfterLoadMoreWithIMMessages:self.needInsertTopIMMessages];
        });
    }
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    if (!decelerate) {
        if (self.needInsertTopIMMessages) {
            //扔到下一个runloop里心里舒坦，强迫症
            dispatch_async(dispatch_get_main_queue(), ^{
                [self insertTopAfterLoadMoreWithIMMessages:self.needInsertTopIMMessages];
            });
        }
    }
}

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (self.dontNeedLazyLoad) {
        return;
    }
    
    if (indexPath.row <=0&&!self.disableLazyLoad) {
        //加载下一页
        [self doSearchForNextPage];
    }
}

#pragma mark - helper
- (void)cancelInput
{
    if (self.chatInputView.inputMode!=IMChatInputModeVoice&&self.chatInputView.inputMode!=IMChatInputModeNone) {
        self.chatInputView.inputMode = IMChatInputModeNone;
    }
}

- (void)scrollToBottomIndexPathWithAnimated:(BOOL)animated
{
    [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self.imMessages.count+1-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:animated];
}

- (void)configureDisplayDateForIMMessages:(NSArray*)imMessages withInitLastDisplayTime:(NSTimeInterval)initLastDisplayTime
{
    //对message设置是否displayDate属性
    NSTimeInterval lastDisplayTime = initLastDisplayTime;
    for (IMMessage *msg in imMessages) {
        //做简单矫正
        if (msg.sendTimestamp<lastDisplayTime) {
            lastDisplayTime = msg.sendTimestamp;
        }
        if (msg.sendTimestamp-lastDisplayTime>kDisplayDateInterval) {
            msg.displayDate = YES;
            lastDisplayTime = msg.sendTimestamp;
        }else{
            msg.displayDate = NO;
        }
        //更改了displayDate，也更新下height，这俩有干连
        msg.heightForCell = 0;
    }
}

- (void)disappearSelfWithAnimated:(BOOL)animated //消失自身
{
    //如果当前有导航器，并且导航器是被present出来的,而且第一个就是self
    if ([self.navigationController.presentingViewController.presentedViewController isEqual:self.navigationController]&&[[self.navigationController.viewControllers firstObject]isEqual:self]) {
        [self.navigationController dismissViewControllerAnimated:animated completion:nil];
    }else{
        //如果当前是被present出来的
        if ([self.presentingViewController.presentedViewController isEqual:self]) {
            [self dismissViewControllerAnimated:animated completion:nil];
        }else{
            [self.navigationController popViewControllerAnimated:animated];
        }
    }
}

- (void)showPicturesWithIMImageMessage:(IMImageMessage*)imImageMessage
{
    NSAssert([self.imMessages containsObject:imImageMessage]&&imImageMessage.imageURL, @"imImageMessage必须有效");
    NSMutableArray *pictureURLs = [NSMutableArray array];
    NSInteger index = 0;
    for (IMMessage *imMsg in self.imMessages) {
        if ([imMsg isKindOfClass:[IMImageMessage class]]) {
            if (CHILD(IMImageMessage, imMsg).imageURL) {
                if (index<=0&&[imMsg isEqual:imImageMessage]) { //找到当前点的那个图片
                    index = pictureURLs.count;
                }
                [pictureURLs addObject:CHILD(IMImageMessage, imMsg).imageURL];
            }
        }
    }
    [[MLPictureBrowser new]showWithPictureURLs:pictureURLs atIndex:index];
}

- (NSInteger)imAudioMessageIndexWithAuidoURL:(NSURL*)audioURL
{
    NSInteger index = NSNotFound;
    for (NSInteger i=self.imMessages.count-1; i>=0; i--) {
        IMMessage *imMsg = self.imMessages[i];
        if (![imMsg isKindOfClass:[IMAudioMessage class]]||![CHILD(IMAudioMessage, imMsg).audioURL isEqual:audioURL]) {
            continue;
        }
        index = i;
        break;
    }
    return index;
}

- (NSArray*)combinationsOfChatMoreView
{
    //构造元素数组
    MLElementButtonItemCombination *combination = [MLElementButtonItemCombination new];
    combination.elementWidth = 60.0f;
    combination.elementHeight = combination.elementWidth+18.0f;
    combination.elementXSpacing = 7.5f;
    combination.elementYSpacing = 5.0f;
    combination.buttonContentMode = UIViewContentModeScaleAspectFill;
    combination.customTitleColor = [UIColor colorWithRed:0.486 green:0.490 blue:0.498 alpha:1.000];
//            combination.bkgImageName = [IMIMG_BUNDLE_NAME stringByAppendingPathComponent:@"更多_背景"];
    
    NSMutableArray *items = [NSMutableArray array];
    NSMutableArray *names = [NSMutableArray array];
    NSMutableArray *imageNames = [NSMutableArray array];
    NSMutableArray *clickBlocks = [NSMutableArray array];
    
    WEAKSELF
    if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
        [names addObject:@"相册"];
        [imageNames addObject:[IMIMG_BUNDLE_NAME stringByAppendingPathComponent:@"更多_相册"]];
        MLElementButtonItemClickBlock clickBlock = ^(MLElementButtonView *elementView,MLElementButtonItem *elementItem){
            STRONGSELF
            [sSelf selectPictureWithSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
        };
        [clickBlocks addObject:[clickBlock copy]];
    }
    if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
        [names addObject:@"相机"];
        [imageNames addObject:[IMIMG_BUNDLE_NAME stringByAppendingPathComponent:@"更多_相机"]];
        MLElementButtonItemClickBlock clickBlock = ^(MLElementButtonView *elementView,MLElementButtonItem *elementItem){
            STRONGSELF
            [sSelf selectPictureWithSourceType:UIImagePickerControllerSourceTypeCamera];
        };
        [clickBlocks addObject:[clickBlock copy]];
    }
    
    for (NSInteger i=0; i<names.count; i++) {
        MLElementButtonItem *item = [MLElementButtonItem new];
        item.name = names[i];
        item.imageName = imageNames[i];
        item.customClickBlock = clickBlocks[i];
        [items addObject:item];
    }
    
    combination.elements = items;
    
    return @[combination];
}

#pragma mark - select picture
- (void)selectPictureWithSourceType:(UIImagePickerControllerSourceType)sourceType
{
    [[MLKitManager manager] selectPictureWithSourceType:sourceType maxCompressedImageSize:IM_PICTURE_MAX_FILE_SIZE callback:^(UIImage *image,NSData *compressedData, MLURL *url) {
        IMImageMessage *imMsg = [IMImageMessage new];
        imMsg.imageURL = url;
        imMsg.imageHeight = image.size.height;
        imMsg.imageWidth = image.size.width;
        [self replyIMMessage:imMsg];
    }];
}

#pragma mark - message add
- (void)replyIMMessage:(IMMessage*)imMessage
{
    [IMCM replyNewIMMessage:imMessage toIMConvId:self.imConv.conversationId];
}

- (void)addIMMessages:(NSArray*)imMessages
{
    BOOL scrollToBottom = NO;
    //查看当前最后显示的cell是否处于最后五个之内，如果是的话就滚动到最后
    NSIndexPath *bottomVisibleIndexPath = [[self.tableView indexPathsForVisibleRows]lastObject];
    if (self.imMessages.count+1<5||bottomVisibleIndexPath.row>=self.imMessages.count+1-5) {
        scrollToBottom = YES;
    }
    
    NSMutableArray *indexes = [NSMutableArray array];
    
    for (NSUInteger i=0; i<imMessages.count; i++) {
        [indexes addObject:[NSIndexPath indexPathForRow:i+self.imMessages.count+1 inSection:0]];
        
        if (!scrollToBottom) {
            //如果有自己发的信息也是滚动到底部。例如音频
            IMMessage *imMsg = imMessages[i];
            if (IMISME(imMsg.clientId)) {
                scrollToBottom = YES;
            }
        }
    }
    
    //找到当前的最后displayTime
    __block NSTimeInterval currentLastDisplayTime = 0;
    [self.imMessages enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        if (CHILD(IMMessage, obj).displayDate) {
            currentLastDisplayTime = CHILD(IMMessage, obj).sendTimestamp;
            *stop = YES;
        }
    }];
    //这里因为重发的消息时间变动造成上个计算的时间不太合适的矫正
    if (CHILD(IMMessage, [self.imMessages lastObject]).sendTimestamp<currentLastDisplayTime) {
        currentLastDisplayTime = CHILD(IMMessage, [self.imMessages lastObject]).sendTimestamp;
    }
    
    [self configureDisplayDateForIMMessages:imMessages withInitLastDisplayTime:currentLastDisplayTime];
    
    [self.imMessages addObjectsFromArray:imMessages];
    
    [CATransaction setDisableActions:YES];
    [self.tableView insertRowsAtIndexPaths:indexes withRowAnimation:UITableViewRowAnimationAutomatic];
    [CATransaction setDisableActions:NO];
    
    if (scrollToBottom) {
        [self scrollToBottomIndexPathWithAnimated:YES];
    }
}

#pragma mark - lazyload
- (void)doSearchForNextPage
{
    self.disableLazyLoad = YES;
    [self.moreCell animatingLoadMoreCell:YES];
    
    //找到当前最早的messageId
    IMMessage *firstMessage = [self.imMessages firstObject];
//    NSTimeInterval beginTime = [[NSDate date]timeIntervalSince1970];
    [IMCM webIMMessagesWithIMConvId:self.imConv.conversationId beforeIMMessage:firstMessage count:kMLIM_MaxBackupMessageCount callback:^(NSArray *objects, NSError *error) {
        if (error) {
            [self.moreCell animatingLoadMoreCell:NO];
            return;
        }
        if (!objects) {
            //这样的话在scrollViewDidEndDecelerating等方法里好区分
            objects = @[];
        }

//        dispatch_async(dispatch_get_main_queue(), ^{
//            [self insertTopAfterLoadMoreWithIMMessages:objects];
//        });
        //给0.05f让loading有显示的机会，例如在直接点状态栏到列表头部而触发的懒加载时。
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.05f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [self insertTopAfterLoadMoreWithIMMessages:objects];
        });
        //下面这个一开始是为啥需要这样写，真的很疑惑。。。防止以后发现它的有用之处还是先不删掉吧。。
        
//        NSTimeInterval currentTime = [[NSDate date]timeIntervalSince1970];
//        //保证有延迟
//        NSTimeInterval delay = MAX(currentTime-beginTime,0.1);
//        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//            [self insertTopAfterLoadMoreWithIMMessages:objects];
//        });
    }];
}

- (void)insertTopAfterLoadMoreWithIMMessages:(NSArray*)objects
{
    //这个是为了防止按住时候引起下面的修正contentOffset有误的BUG
    //还有防止在减速时候插入对象引起的动画停止不好的体验。
    if (self.tableView.isDragging||self.tableView.isDecelerating) {
        self.needInsertTopIMMessages = objects;
        return;
    }
    self.needInsertTopIMMessages = nil;
    
    //去重
    NSMutableArray *oldIMMessages = [objects mutableCopy];
    NSMutableArray *needRemoveObjects = [NSMutableArray array];
    for (IMMessage *imMsg in oldIMMessages) {
        for (IMMessage *rIMMsg in self.imMessages) {
            if ([rIMMsg.messageId isEqualToString:imMsg.messageId]) {
                [needRemoveObjects addObject:imMsg];
            }
        }
    }
    if (needRemoveObjects.count>0) {
        [oldIMMessages removeObjectsInArray:needRemoveObjects];
    }
    
    
    //加入到上一页,这个要是objects，不能是oldIMMessages
    if (objects.count<kMLIM_MaxBackupMessageCount) {
        //不需要懒加载了
        DLOG(@"不需要懒加载了");
        self.dontNeedLazyLoad = YES;
    }
    
    //要插入的为0行，直接返回即可
    if (oldIMMessages.count<=0) {
        if (self.dontNeedLazyLoad) {
            [self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationAutomatic];
        }
        return;
    }
    
    [self configureDisplayDateForIMMessages:oldIMMessages withInitLastDisplayTime:0];
    
    //插入到头部
    NSMutableArray *indexes = [NSMutableArray array];
    for (NSUInteger i=0; i<oldIMMessages.count; i++) {
        [indexes addObject:[NSIndexPath indexPathForRow:i+1 inSection:0]];
    }
    
    NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, oldIMMessages.count)];
    
    BOOL isNeedReBakcupMessages = NO;
    if (self.imMessages.count<kMLIM_MaxBackupMessageCount) {
        isNeedReBakcupMessages = YES;
    }
    
    [self.imMessages insertObjects:oldIMMessages atIndexes:indexSet];
    
    CGPoint offset = self.tableView.contentOffset;
    
    [CATransaction setDisableActions:YES];
    
    CGFloat heightForNewRows = 0;
    for (NSIndexPath *indexPath in indexes) {
        heightForNewRows += [self tableView:self.tableView heightForRowAtIndexPath:indexPath];
    }
    if (self.dontNeedLazyLoad) {
        heightForNewRows -= kLoadMoreCellHeight;
    }
    
    [self.tableView beginUpdates];
    if (self.dontNeedLazyLoad) {
        [self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationAutomatic];
    }
    [self.tableView insertRowsAtIndexPaths:indexes withRowAnimation:UITableViewRowAnimationAutomatic];
    [self.tableView endUpdates];
    
    offset.y += heightForNewRows;
    
    [self.tableView setContentOffset:offset animated:NO];
    
    [CATransaction setDisableActions:NO];
    
    self.disableLazyLoad = NO;
    
    if (isNeedReBakcupMessages) {
        [IMCM archiverIMMessages:self.imMessages toIMConvId:self.imConv.conversationId callback:^(BOOL succeeded, NSError *error) {
            if (!self.imConv.lastMessage) { //这个是有点特别的情况，特殊处理下
                self.imConv.lastMessage = [self.imMessages lastObject];
                
                //通知会话刷新
                [[NSNotificationCenter defaultCenter]postNotificationName:MLIM_IMConversation_UpdateDetail_Notification object:nil userInfo:@{@"archiver":@(YES),@"imConvs":@[self.imConv]}];
            }
        }];
    }
}

#pragma mark - menu
- (void)tapBackgroundImageViewWithCell:(IMMessageTableViewCell*)cell
{
    IMMessage *imMsg = cell.imMessage;
    if (!imMsg) {
        return;
    }
}

#define kOverlayViewTag 598
- (void)longPressBackgroundImageViewWithCell:(IMMessageTableViewCell*)cell
{
    IMMessage *imMsg = cell.imMessage;
    if (!imMsg) {
        return;
    }
    IMMessageBackgroundImageView *view = cell.backgroundImageView;
    HPTextViewInternal *textView = (HPTextViewInternal*)(self.chatInputView.textView.internalTextView);
    if ([textView isFirstResponder]) {
        textView.overrideNextResponder = view;
    }else{
        [view becomeFirstResponder];
    }
    
    NSMutableArray *items = [NSMutableArray array];
    if ([imMsg isKindOfClass:[IMTextMessage class]]) {
        [items addObject:[[UIMenuItem alloc]initWithTitle:@"复制" action:@selector(copyContent:)]];
    }
    if (imMsg.status == IMMessageStatusSendFailed) {
        [items addObject:[[UIMenuItem alloc]initWithTitle:@"重发" action:@selector(reSendMessage:)]];
    }
    
    UIMenuController *menu = [UIMenuController sharedMenuController];
    [menu setMenuItems:items];
    [menu setTargetRect:view.bounds inView:view];
    
    self.currentMenuCell = cell;
    [view setReSendMessageBlock:^(IMMessageBackgroundImageView *view) {
        [IMCM reSendIMMessage:imMsg];
    }];
    
    [view setCopyContentBlock:^(IMMessageBackgroundImageView *view) {
        if ([imMsg isKindOfClass:[IMTextMessage class]]) {
            [[UIPasteboard generalPasteboard] setString:CHILD(IMTextMessage, imMsg).content];
        }
    }];
    
    [menu setMenuVisible:YES animated:YES];
}

- (void)menuWillShow:(NSNotification*)notification {
    if (!self.currentMenuCell) {
        return;
    }
    
    self.tabelViewTapGesture.enabled = NO;
    
    [self.currentMenuCell changeBackgroundImageToDark:YES];
}

- (void)menuWillHide:(NSNotification*)notification {
    if (!self.currentMenuCell) {
        return;
    }
    
    HPTextViewInternal *textView = (HPTextViewInternal*)(self.chatInputView.textView.internalTextView);
    textView.overrideNextResponder = nil;
    
    [self.currentMenuCell changeBackgroundImageToDark:NO];
    [self.currentMenuCell.backgroundImageView resignFirstResponder];
    
    self.tabelViewTapGesture.enabled = YES;
    self.currentMenuCell = nil;
}


@end
